package com.dbsop.transport.handler;

import com.dbsop.common.util.EsFieldUtils;
import com.dbsop.common.util.ValuesUtils;
import com.dbsop.domain.info.EsFiledInfo;
import com.dbsop.wrapper.DataWrapper;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * TCP 形势的记录值处理
 */
public class TcRecordHandler {


    private static SearchHit[] hits(SearchResponse searchResponse){
        SearchHits hitsChild = searchResponse.getHits();
        if (hitsChild == null){
            return null;
        }
        SearchHit[] hitsArr = hitsChild.getHits();
        if (hitsArr == null || hitsArr.length == 0){
            return null;
        }
        return hitsArr;
    }

    /**
     * 记录处理成map
     * @param searchResponse
     * @return
     */
    public static List<Map<String,Object>> recordsToMap(SearchResponse searchResponse){
        List<Map<String,Object>> dataList = new ArrayList<Map<String, Object>>();
        SearchHit[] hitsArr = hits(searchResponse);
        if (hitsArr == null) {
            return dataList;
        }
        for (SearchHit documentFields : hitsArr) {
            Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
            dataList.add(sourceAsMap);
        }
        return dataList;
    }

    /**
     *  记录处理
     * @param searchResponse
     * @param clazz
     * @param <T>
     * @return
     */
    public static   <T> List<T> records(SearchResponse searchResponse, Class<T> clazz, DataWrapper<T> dataWrapper){
        List<T> dataList = new ArrayList<T>();
        SearchHit[] hitsArr = hits(searchResponse);
        if (hitsArr == null) {
            return dataList;
        }
        return recordsHits(hitsArr,clazz,dataWrapper);
    }


    public static   <T> List<T> recordsHits(SearchHit[] searchHits, Class<T> clazz, DataWrapper<T> dataWrapper){
        List<T> dataList = new ArrayList<T>();
        Map<String, EsFiledInfo> fieldMap = EsFieldUtils.pareFieldEsInfo(clazz);

        if (clazz!=null){
            for (SearchHit documentFields : searchHits) {
                Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
                if (clazz == Map.class){
                    dataList.add((T) sourceAsMap);
                    continue;
                }
                if (sourceAsMap == null)continue;
                T t = null;
                try {
                    t = clazz.newInstance();
                    ValuesUtils.fieldAssignment(fieldMap,t,sourceAsMap);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e.getCause());
                }
                dataList.add(t);
            }
            return dataList;
        }

        if (dataWrapper!=null){
            for (SearchHit documentFields : searchHits) {
                T wrapper = dataWrapper.wrapper(documentFields.getSourceAsMap());
                if (wrapper !=null){
                    dataList.add(wrapper);
                }

            }
            return dataList;
        }

        return dataList;
    }


    /**
     * 排名数据解析
     * @param searchResponse
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> rankingRecord(SearchResponse searchResponse, Class<T> clazz, DataWrapper<T> dataWrapper) {
        List<T> dataList = new ArrayList<T>();
        SearchHit[] searchHits = hits(searchResponse);
        if (searchHits == null || searchHits.length == 0){
            return dataList;
        }
        Map<String,List<T>> dataMap = new LinkedHashMap<String,List<T>>();
        if (clazz!=null){
            for (SearchHit searchHit : searchHits) {
                Map<String, SearchHits> innerHits = searchHit.getInnerHits();
                innerHits.forEach((key, val) -> {
                    SearchHit[] hits = val.getHits();
                    if (hits == null || hits.length == 0){
                        return;
                    }
                    List<T> ts = recordsHits(hits, clazz, dataWrapper);
                    if (ts == null){
                        ts = new ArrayList<T>();
                    }
                    if (dataMap.get(key) == null){
                        dataMap.put(key,ts);
                    }else {
                        dataMap.get(key).addAll(ts);
                    }
                });
            }
            if (dataMap.size() == 1){
                for (String key : dataMap.keySet()){
                    if (dataMap.get(key)!=null){
                        dataList.addAll(dataMap.get(key));
                    }
                }
            }
        }
        return dataList;
    }
}
